ci: daily LoC report to Slack (daily) and Telegram (weekly)#368
ci: daily LoC report to Slack (daily) and Telegram (weekly)#368MegaRedHand wants to merge 4 commits into
Conversation
Adds a scheduled workflow that counts Rust LoC in the workspace and publishes a report to Slack daily and to Telegram weekly (Monday UTC). Day-over-day deltas are computed against the previous run's report, cached on the branch under `loc-report-<ref_name>-` keys. Required secrets: ETHLAMBDA_GENERAL_SLACK_WEBHOOK prod Slack channel ETHLAMBDA_TEST_SLACK_WEBHOOK test Slack channel (manual runs) TELEGRAM_BOT_TOKEN bot token TELEGRAM_ETHLAMBDA_CHAT_ID prod Telegram chat TELEGRAM_ETHLAMBDA_TEST_CHAT_ID test Telegram chat (manual runs)
🤖 Kimi Code ReviewCritical Issues
Performance & Maintainability
Minor Issues
Correctness Acknowledged
Recommendation: Fix Item 1 (checkout version) and Item 3 (null handling) before merging. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Claude Code ReviewHere is the review of PR #368: PR #368 Review: Daily LoC Report to Slack / TelegramOverview: Adds a scheduled GitHub Actions workflow ( Bug: First-run failure on the
|
🤖 Codex Code ReviewFindings
No consensus-layer Rust paths are touched in this PR, so I didn’t see fork-choice/state-transition/XMSS/SSZ concerns beyond these workflow issues. Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Greptile SummaryThis PR adds a new scheduled GitHub Actions workflow that counts Rust lines of code across all workspace members daily, posts a Slack Block Kit message every day, and sends an HTML Telegram message on Mondays (or on-demand). Day-over-day deltas are computed by caching and restoring the previous run's JSON report.
Confidence Score: 4/5Safe to merge; all changes are additive CI scripts with no impact on application code. The core delta/cache logic and conditional routing are sound. The main actionable issue is in publish_slack.sh, where the :? expansion silently swallows the more descriptive check-your-secret error message that was clearly intended to guide operators on misconfiguration. Two other findings (webhook URL in argv, src/-only LoC scanning) do not break functionality. publish_slack.sh needs the dead-code guard fixed so the informative error message is actually reachable.
|
| Filename | Overview |
|---|---|
| .github/scripts/generate_loc_report.sh | Counts Rust LoC per workspace member via tokei + cargo metadata, computes day-over-day deltas from a cached old report, and writes Slack/Telegram/GitHub Step Summary payloads; LoC counting is silently skipped (0) for any crate lacking a src/ subdirectory. |
| .github/scripts/publish_slack.sh | POSTs the Slack Block Kit payload via curl; the intended informative error message for a missing webhook secret is unreachable because the :? expansion already exits before the if [[ -z ... ]] guard. |
| .github/scripts/publish_telegram.sh | Sends an HTML-formatted Telegram message; validation of required env vars is correct (uses :- to avoid unbound-var errors with set -u), and URL-encoding of the message body is handled by --data-urlencode. |
| .github/workflows/daily_loc_report.yml | Defines the scheduled/manual workflow with correct cache-hit gating for delta computation, conditional Slack/Telegram routing, and a Monday-only guard for Telegram on scheduled runs; webhook URL is passed as a positional argument rather than an env var. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([Trigger: schedule 0 0 * * * / workflow_dispatch]) --> B[Checkout + Setup Rust + tokei]
B --> C[Restore cache\nloc-report-branch-runid]
C -->|cache-hit != ''| D[mv loc_report.json to loc_report.json.old]
C -->|cache-hit == ''| E[No delta baseline - first run]
D --> F[generate_loc_report.sh]
E --> F
F --> G[Save loc_report.json to cache]
G --> H[Append to GITHUB_STEP_SUMMARY]
H --> I{schedule or target=prod?}
I -->|yes| J[SLACK_WEBHOOK = GENERAL]
I -->|no| K[SLACK_WEBHOOK = TEST]
J --> L[publish_slack.sh]
K --> L
L --> M{schedule?}
M -->|yes, day != Monday| N[Skip Telegram]
M -->|yes, Monday| O[publish_telegram.sh]
M -->|no / workflow_dispatch| P{post_telegram=true?}
P -->|yes| O
P -->|no| N
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
.github/scripts/publish_slack.sh:9-15
The `[[ -z "$WEBHOOK_URL" ]]` guard on lines 12-15 is dead code and can never be reached. The `${1:?webhook URL required}` expansion on line 9 already causes the script to exit with an error if `$1` is empty or unset — so by the time execution reaches the `if` block, `WEBHOOK_URL` is guaranteed to be non-empty. The informative `::error::` annotation with the secrets-troubleshooting message is therefore never surfaced to the operator.
```suggestion
WEBHOOK_URL="${1}"
PAYLOAD_FILE="${2:?payload file required}"
if [[ -z "$WEBHOOK_URL" ]]; then
echo "::error::Slack webhook URL resolved to an empty value — check the secret configured for this trigger (scheduled vs manual)"
exit 1
fi
```
### Issue 2 of 3
.github/workflows/daily_loc_report.yml:82
**Webhook URL passed as positional CLI argument**
`$SLACK_WEBHOOK` is expanded into the command line, making it visible in `ps` output for the duration of the `curl` call. Passing it via an environment variable (as is already done for `TELEGRAM_BOT_TOKEN`) keeps it out of the process argument list. The script already has `SLACK_WEBHOOK` as an env var, so you could read it directly from there instead of forwarding it as `$1`.
### Issue 3 of 3
.github/scripts/generate_loc_report.sh:42-47
**LoC count limited to `src/` subdirectory only**
Crates that place Rust source in directories other than `src/` — for example, a `proc-macro` sub-crate that uses a flat layout, or a virtual workspace member with code directly at the crate root — will be counted as 0 LoC. The tokei call would still find their `.rs` files if pointed at the crate root (`$dir`), but the current code skips any crate where `$dir/src` does not exist. This is worth a clarifying comment if the workspace layout is always conventional.
Reviews (1): Last reviewed commit: "ci: add daily LoC report workflow" | Re-trigger Greptile
| WEBHOOK_URL="${1:?webhook URL required}" | ||
| PAYLOAD_FILE="${2:?payload file required}" | ||
|
|
||
| if [[ -z "$WEBHOOK_URL" ]]; then | ||
| echo "::error::Slack webhook URL resolved to an empty value — check the secret configured for this trigger (scheduled vs manual)" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
The
[[ -z "$WEBHOOK_URL" ]] guard on lines 12-15 is dead code and can never be reached. The ${1:?webhook URL required} expansion on line 9 already causes the script to exit with an error if $1 is empty or unset — so by the time execution reaches the if block, WEBHOOK_URL is guaranteed to be non-empty. The informative ::error:: annotation with the secrets-troubleshooting message is therefore never surfaced to the operator.
| WEBHOOK_URL="${1:?webhook URL required}" | |
| PAYLOAD_FILE="${2:?payload file required}" | |
| if [[ -z "$WEBHOOK_URL" ]]; then | |
| echo "::error::Slack webhook URL resolved to an empty value — check the secret configured for this trigger (scheduled vs manual)" | |
| exit 1 | |
| fi | |
| WEBHOOK_URL="${1}" | |
| PAYLOAD_FILE="${2:?payload file required}" | |
| if [[ -z "$WEBHOOK_URL" ]]; then | |
| echo "::error::Slack webhook URL resolved to an empty value — check the secret configured for this trigger (scheduled vs manual)" | |
| exit 1 | |
| fi |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/scripts/publish_slack.sh
Line: 9-15
Comment:
The `[[ -z "$WEBHOOK_URL" ]]` guard on lines 12-15 is dead code and can never be reached. The `${1:?webhook URL required}` expansion on line 9 already causes the script to exit with an error if `$1` is empty or unset — so by the time execution reaches the `if` block, `WEBHOOK_URL` is guaranteed to be non-empty. The informative `::error::` annotation with the secrets-troubleshooting message is therefore never surfaced to the operator.
```suggestion
WEBHOOK_URL="${1}"
PAYLOAD_FILE="${2:?payload file required}"
if [[ -z "$WEBHOOK_URL" ]]; then
echo "::error::Slack webhook URL resolved to an empty value — check the secret configured for this trigger (scheduled vs manual)"
exit 1
fi
```
How can I resolve this? If you propose a fix, please make it concise.| ${{ (github.event_name == 'schedule' || inputs.target == 'prod') | ||
| && secrets.ETHLAMBDA_GENERAL_SLACK_WEBHOOK | ||
| || secrets.ETHLAMBDA_TEST_SLACK_WEBHOOK }} | ||
| run: bash .github/scripts/publish_slack.sh "$SLACK_WEBHOOK" loc_report_slack.json |
There was a problem hiding this comment.
Webhook URL passed as positional CLI argument
$SLACK_WEBHOOK is expanded into the command line, making it visible in ps output for the duration of the curl call. Passing it via an environment variable (as is already done for TELEGRAM_BOT_TOKEN) keeps it out of the process argument list. The script already has SLACK_WEBHOOK as an env var, so you could read it directly from there instead of forwarding it as $1.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/daily_loc_report.yml
Line: 82
Comment:
**Webhook URL passed as positional CLI argument**
`$SLACK_WEBHOOK` is expanded into the command line, making it visible in `ps` output for the duration of the `curl` call. Passing it via an environment variable (as is already done for `TELEGRAM_BOT_TOKEN`) keeps it out of the process argument list. The script already has `SLACK_WEBHOOK` as an env var, so you could read it directly from there instead of forwarding it as `$1`.
How can I resolve this? If you propose a fix, please make it concise.|
@MegaRedHand please how can I stay connected more to development updates via telegram? |
|
@dicethedev We give daily updates on Telegram, sometime post updates on X, and have weekly community calls on Fridays (we post the link on Telegram; it's live on https://x.com/class_lambda). The info is here in the CONTRIBUTING.md (we should probably add that on the readme and docs website 🤦). |
## Summary - Add a **Community** section to the README and `docs/introduction.md` so newcomers find the Telegram group, the weekly Friday community call, and the PQ Interop calls without digging into `CONTRIBUTING.md`. - Refresh the existing **Communication** section in `CONTRIBUTING.md` to match (adds the weekly call and PQ Interop pointers, tightens the Telegram description). Triggered by the follow-up in #368 (comment). ## Test plan - [x] `README.md` renders the new Community section between Contributing and Philosophy. - [x] `docs/introduction.md` renders the new Community section before Related projects (will show up in the mdBook). - [x] `CONTRIBUTING.md` Communication block stays consistent with the other two.
Thanks for letting me know and I also saw your PR reference. LFG! |
Replace the tokei + jq pipeline with cargo-warloc, which parses Rust with `syn` and natively classifies inline `#[cfg(test)]` blocks as test code. The report now shows per-crate counts (no tests) and two totals at the bottom: with and without tests. Reasons: - tokei can only exclude directory names, so unit tests written inline (the dominant pattern here) leaked into the "production" LoC. - Per-crate scanning of crate roots was also missing build.rs. Implementation moves from bash+jq to a small Python script — Python 3 ships on ubuntu-latest, so no extra setup is needed beyond the cargo-warloc install.
Passing the webhook URL as `$1` made it visible in the process list (`ps aux`, `/proc/<pid>/cmdline`) for the duration of the curl call. Switch to reading it from the `SLACK_WEBHOOK` env variable in the script, matching the existing `publish_telegram.sh` pattern.
Summary
.github/workflows/daily_loc_report.yml: scheduled at0 0 * * *UTC plusworkflow_dispatch(withtarget=test/prodand apost_telegramopt-in for manual runs).tokei+cargo metadata, with day-over-day deltas computed against the previous run's report (restored from the branch-scoped Actions cache).Slack and step-summary outputs include total Rust LoC and a per-crate breakdown sorted descending. Excludes
tests/,benches/,examples/.Required secrets / variables
ETHLAMBDA_GENERAL_SLACK_WEBHOOKtarget=prod)ETHLAMBDA_TEST_SLACK_WEBHOOKtarget=test)TELEGRAM_BOT_TOKENTELEGRAM_ETHLAMBDA_CHAT_IDtarget=prod)TELEGRAM_ETHLAMBDA_TEST_CHAT_IDtarget=test)Secret names mirror ethrex's
ETHREX_*pattern — adjust if there are existing conventions in the org.Test plan
target=testandpost_telegram=false— verify the Slack test channel receives the daily message and the workflow step summary shows the per-crate table.target=testandpost_telegram=true— verify Telegram test chat receives the weekly-style message.(+12)/(-3)).target=prodmanual run after secrets are wired to validate the production channel/chat before the first scheduled fire.